#include "registerwin.h"
#include "ui_registerwin.h"
#include <QProcess>
#include <QCryptographicHash>
#include <QFile>

#include <QWidget>
#include <QFrame>
#include <QLabel>
#include <QApplication>
#include <QDesktopWidget>
#include <QPropertyAnimation>


int const RegisterWin::Pass_Register = -123456789;

const QString myPWD = "2444666668888888";   //12345678
/*****************************************
本机器序列号生成方式：
字符串1 = CPU ID + 主硬盘 ID + 自己设置的密码（防止别人知道我是通过cpu ID和硬盘ID生成的序列号，其实知道了也无所谓，这里不是重点）
数组1 = 字符串1通过md5加密得到16字节数据
数组2 = 数组1两两相加得到8字节数据（两两相加后溢出）
最终的序列号字符串 = 数组2数据转为hex格式字符显示
*****************************************/
/*****************************************
最终秘钥生成方式：
字符串1 = 读取资源中的文件内容（公钥），需要与注册机端保持内容一致
数组1 = 字符串1通过md5加密得到16字节数据
数组2 = 数组1 + 计算机序列号（需要被加密的内容）,通过md5加密得到16字节数据
数组3 = 数组1(2n)*数组2(2n) + 数组1(2n + 1)*数组2(2n + 1),得到的8字节数据。这步骤属于自己随意加密的内容，可以多乘以几个数。
最终的序列号字符串 = 数组3数据转为hex格式字符显示
*****************************************/


/**********************************************
主程序使用示范：
#include <QApplication>
#include <registerSys/registerwin.h>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    int buff;
    do
    {
        RegisterWin registeWin;
        registeWin.hide();
        if(registeWin.checkRegister())
            break;
        registeWin.show();
        buff = a.exec();
    }
    while(buff != RegisterWin::Pass_Register);	

    MainWindow mainWin;
    mainWin.show();

    return a.exec();
}
****************************************/
/******************************************
 * 1、首次启动，查询是否有注册文件，如果没有则创建，将首次启动时间等信息写入文件（记得加上校验码校验时间的正确性，文件保密，使用可解码的加密方式）
******************************************/

RegisterWin::RegisterWin(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::RegisterWin)
{
    ui->setupUi(this);
    this->setWindowFlags(Qt::FramelessWindowHint);
    this->setWindowTitle("软件注册");
    this->setWindowIcon(QIcon(":/new/prefix1/log.png"));
    ui->stackedWidget->setCurrentIndex(0);
}

RegisterWin::~RegisterWin()
{
    delete ui;
}

bool RegisterWin::checkRegister()       //判断注册码是否有效
{
    return 0;
}

void RegisterWin::on_pushButton_shutDown_clicked()  //立马关机
{

}

void RegisterWin::on_pushButton_turn2_clicked()     //转到注册界面
{
    QString cpuID = getCpuId();
    QString diskID = getDiskNum();
    QString computeSerial = cpuID + diskID + myPWD;
    QByteArray hashData = QCryptographicHash::hash(computeSerial.toLocal8Bit(),QCryptographicHash::Md5);
    QByteArray hashData2;
    for(int i = 0;i < hashData.size()/2;i ++)
    {
        char buff = hashData.at(2*i) + hashData.at(2*i+1);
        hashData2.append(buff);
    }
    QString showSerial = HexToHexstr(hashData2);
    showSerial.remove(QRegExp("\\s"));
    ui->lineEdit_serial->setText(showSerial);
    ui->stackedWidget->setCurrentIndex(1);
}

void RegisterWin::on_pushButton_turn1_clicked()     //返回到关机界面
{
    ui->stackedWidget->setCurrentIndex(0);
}

void RegisterWin::on_pushButton_Ok_clicked()        //进行注册对比
{
    QString localSerial = ui->lineEdit_serial->text().trimmed();
    QString inputRegister = ui->lineEdit_register->text().trimmed();
    if(inputRegister.isEmpty())
    {
        showHintLabel(nullptr,"请输入注册码后确认！");
        return;
    }
    QFile publicKey(":/publicKey.p");
    if(!publicKey.open(QIODevice::ReadOnly))
    {
        showHintLabel(nullptr,"找不到公钥，本次注册失败！");
        return;
    }
    QByteArray keyData = publicKey.readAll();

    QString cacul_Register = caculateRegister(localSerial,keyData);
    if(cacul_Register == inputRegister)
        qApp->exit(RegisterWin::Pass_Register); //表示通过注册
    else
        showHintLabel(nullptr,"注册码错误！请重新输入。");  //不通过注册
}

QString RegisterWin::caculateRegister(QString serial,QByteArray keyData)
{
    QByteArray hashData = QCryptographicHash::hash(keyData,QCryptographicHash::Md5);
    hashData += serial.toLocal8Bit();
    QByteArray hashData2 = QCryptographicHash::hash(hashData,QCryptographicHash::Md5);
    QByteArray lastData;
    for(int i = 0;i < hashData2.size()/2;i ++)
    {
        char buff = hashData2.at(2*i)*hashData.at(2*i) + hashData2.at(2*i+1)*hashData.at(2*i+1);
        lastData.append(buff);
    }
    QString caculateRegister = HexToHexstr(lastData).remove(QRegExp("\\s"));
    return caculateRegister;
}

void RegisterWin::widgetCenter(QWidget *pWidget, QWidget *parent)
{
    QSize parentSize = (nullptr == parent) ? QApplication::desktop()->screenGeometry().size() : parent->size(); //双屏情况下在主屏幕上提示
    QSize subSize = parentSize - pWidget->size();

    pWidget->move(subSize.width()/2,subSize.height()/2);
}

void RegisterWin::showHintLabel(QWidget *parent, QString strText, QString strFontSize, QString strColor, QString strBgColor)
{
    if(nullptr == parent){
        parent = QApplication::desktop()->screen();
    }

    QFrame *pFrame = new QFrame(parent);        //为了兼容parent为nullptr时的圆角边框  方法是背景透明 上边叠加圆角控件
    QLabel *pLabel = new QLabel(pFrame);    //创建显示标签
    pLabel->setStyleSheet(QString("QLabel{background:%1;color:%2;font:%3 SimHei;border-radius:5px;}")
                              .arg(strBgColor).arg(strColor).arg(strFontSize)); //社长标签风格
    pLabel->setText(strText);   //设置标签内容
    pLabel->setAlignment(Qt::AlignCenter);
    pLabel->adjustSize();
    pLabel->resize(pLabel->size() + QSize(180,150));

    pFrame->resize(pLabel->size());                     //设置大小为label大小
    pFrame->setWindowFlags(Qt::FramelessWindowHint);    //去除外框
    pFrame->setAttribute(Qt::WA_TranslucentBackground);
    pFrame->move((parent->width()-pFrame->width())/2,(parent->height()-pFrame->height())/2);
    pFrame->show();

    QPropertyAnimation *pAnimation = new QPropertyAnimation(pFrame,"windowOpacity",this);
    pAnimation->setDuration(2000);
    pAnimation->setEasingCurve(QEasingCurve::InCirc);
    pAnimation->setStartValue(1.0);
    pAnimation->setEndValue(0.0);
    pAnimation->start();
    connect(pAnimation,&QPropertyAnimation::finished,[=]{
        delete pAnimation;
        delete pFrame;
    });
}

/*******************************************
时间：2019-4-22 10点42分
作者：Kiang Tao
功能：HEX数组转HEX字符串
输入参数：hex数组  如：01 ff 0f f0
返回值：hex字符串  如："01 ff 0f f0"
*******************************************/
QString RegisterWin::HexToHexstr(const QByteArray hex)
{
    //QString::number(hex,16);
    if(hex.isEmpty())   return "";
    QByteArray DataIn = hex;
    QString HexStr;
    QDataStream DataStream(&DataIn,QIODevice::ReadWrite);
    while(!DataStream.atEnd())
    {
        quint8 outChar = 0;
        DataStream >> outChar;
        HexStr += QString("%1").arg(outChar & 0xff,2,16,QLatin1Char('0'))+" ";
    }
    return HexStr.toUpper();    //换大写字母
}

QString RegisterWin::getWMIC(const QString &cmd)
{
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();
    return result;
}
QString RegisterWin::getCpuName()    //获取cpu名称：wmic cpu get Name
{
    return getWMIC("wmic cpu get name");
}
QString RegisterWin::getCpuId()  //查询cpu序列号：wmic cpu get processorid
{
    return getWMIC("wmic cpu get processorid");
}
QString RegisterWin::getCpuCoresNum()    //获取cpu核心数：wmic cpu get NumberOfCores
{
    return getWMIC("wmic cpu get NumberOfCores");
}
QString RegisterWin::getCpuLogicalProcessorsNum() //获取cpu线程数：wmic cpu get NumberOfLogicalProcessors
{
    return getWMIC("wmic cpu get NumberOfLogicalProcessors");
}
QString RegisterWin::getDiskNum()    //查看主硬盘序列号：wmic diskdrive get serialnumber
{
    return getWMIC("wmic diskdrive where index=0 get serialnumber");
}
QString RegisterWin::getBaseBordNum()    //查询主板序列号：wmic baseboard get serialnumber
{
    return getWMIC("wmic baseboard get serialnumber");
}
QString RegisterWin::getBiosNum()    //查询BIOS序列号：wmic bios get serialnumber
{
    return getWMIC("wmic bios get serialnumber");
}


